import React, { Component , PropTypes } from 'react';

import styles from './style.scss';

const getElementSize = el => {
    const { top , height } = el.getBoundingClientRect();
    return {
        top:top <= 0 ? 0 : top,
        height:height
    };
};

export default class LoadImageWrapper extends Component {

    static propTypes = {
        //图片地址
        src: PropTypes.string,
        className: PropTypes.string,
        //是否懒加载
        lazyLoad:PropTypes.bool,
        style:()=>PropTypes.style,
        onClick:PropTypes.func,
        animate:PropTypes.bool,
        resizeMode:PropTypes.oneOf(["cover","contain"])
    };

    static defaultProps = {
        className: "",
        src:null,
        lazyLoad:false,
        onClick:()=>{},
        animate:true,
        resizeMode:"cover"
    };

    static contextTypes = {
        iScroll: PropTypes.object
    };

    iScroll(){
        return (this.context || {}).iScroll;
    }

    show(){
        const { lazyLoad } = this.props;
        return lazyLoad ? !!this.iScroll() : true;
    }

    render() {
        return this.show() ?
            <LoadImage
                {...this.props}
                iScroll={this.iScroll()}
            /> :
            null
    }
}


class LoadImage extends Component {

    constructor() {
        super();

        this.timeout = [];
        this.unMount = false;
        //图片加载中..
        this.loading = false;
        //溢出
        this.overflow = 40;
        this.state = {
            //是否加载过了
            loaded: false,
            isError: false
        };
        this.showImageEvent = this.showImageEvent.bind(this);
    }

    static propTypes = {
        ...LoadImageWrapper.propTypes
    };

    static defaultProps = {
        ...LoadImageWrapper.defaultProps
    };

    componentDidMount() {

        const {
            src,
            lazyLoad
        } = this.props;

        if(!!src) {
            lazyLoad ? this.lazyLoad() : this.loadImage();
        }
    }

    lazyLoad(){
        this.bindScrollEvent();
    }

    loadImage(){
        const { src } = this.props;
        if(this.loading) return;
        this.loading = true;
        const image = new Image();
        image.src = src;
        //成功
        this.timeout.push(
            setTimeout( ()=> {
                this.unBindScrollEvent();
            },100)
        );
        image.onload = function () {
            this.setState({
                loaded:true
            });
        }.bind(this);
        //失败
        image.onerror = function () {
            this.setState({
                isError:true
            });
        }.bind(this);
    }

    bindScrollEvent() {
        this.iScroll = (this.props || {}).iScroll;
        if (!this.iScroll) return false;
        this.iScroll.on("beforeScrollStart", this.showImageEvent);
        this.iScroll.on("scroll", this.showImageEvent);
        this.iScroll.on("scrollEnd", this.showImageEvent);
        this.timeout.push(setTimeout( () => (
            this.showImageEvent()
        ), 10));
    }

    unBindScrollEvent(){
        if(!this.iScroll ) return false;
        this.iScroll.off("beforeScrollStart", this.showImageEvent);
        this.iScroll.off("scroll", this.showImageEvent);
        this.iScroll.off("scrollEnd", this.showImageEvent);
    }

    showImageEvent() {
        const { wrapperHeight, wrapperOffset } = this.iScroll;
        const elSize = getElementSize(this.el);
        const offsetTop = elSize.top + wrapperOffset.top;
        if ( offsetTop + elSize.height - this.overflow <= wrapperHeight) this.loadImage();
    }

    componentWillUnmount() {
        this.unMount = true;
        this.unBindScrollEvent();
        this.timeout.forEach(t=>clearTimeout(t));
    }

    resizeMode (mode) {
        switch (mode) {
            case "cover":
                return styles.mode_cover;
            case "contain":
                return styles.mode_contain;
        }
    }

    render() {
        const { src , className , style , onClick , animate , resizeMode } = this.props;
        const { loaded , isError } = this.state;
        const bgStyle = loaded ? { backgroundImage:`url(${src})` } : null;
        return (
            <div
                style={style}
                ref={e=>this.el=e}
                onClick={(e)=>onClick(e)}
                className={classname(
                    styles.load_image_wrapper,
                    className
                )}
            >
                {!!src ?
                    <div className={styles.load_image_content}>
                        <div
                            style={bgStyle}
                            className={classname(
                                styles.image_show_bg,
                                this.resizeMode(resizeMode)
                            )}
                        />
                        {!isError ?
                            <div className={classname(
                                styles.load_cover,
                                animate && styles.cover_animate,
                                loaded && styles.cover_hide
                            )}/> :
                            <div data-role="error" className={classname(
                                styles.load_cover,
                                styles.load_cover_error
                            )}/>
                        }
                    </div> :
                    <div
                        className={styles.load_cover}
                        data-role="no-src"
                    />
                }
            </div>
        )
    }
}

